home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Draw Editor / Source / Selection.cpp < prev    next >
Encoding:
Text File  |  1995-12-11  |  32.9 KB  |  1,301 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Selection.cpp
  3.  
  4.     Contains:    Selection Classes Implementation
  5.  
  6.     Written by:    Dave Stafford
  7.     
  8.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. // -- DrawEditor Includes --
  12.  
  13. #ifndef _COMPILERDEFS_
  14. #include "CompDefs.h"
  15. #endif
  16.  
  17. #ifndef _DRAWEDTORUTILS_
  18. #include "DrawEditorUtils.h"
  19. #endif
  20.  
  21. #ifndef _SELECTION_
  22. #include "Selection.h"
  23. #endif
  24.  
  25. #ifndef _LINK_
  26. #include "Link.h"
  27. #endif
  28.  
  29. #ifndef _DRAWEDITOR_
  30. #include "DrawEditor.h"
  31. #endif
  32.  
  33. #ifndef _DRAWEDITORUTILS_
  34. #include "DrawEditorUtils.h"
  35. #endif
  36.  
  37. #ifndef _SHAPECOMMANDS_
  38. #include "ShapeCommands.h"
  39. #endif
  40.  
  41. #ifndef _SHAPES_
  42. #include "Shapes.h"
  43. #endif
  44.  
  45. // -- OpenDoc Includes --
  46.  
  47. #ifndef SOM_ODDraft_xh
  48. #include <Draft.xh>
  49. #endif
  50.  
  51. #ifndef SOM_ODShape_xh
  52. #include <Shape.xh>
  53. #endif
  54.  
  55. #ifndef SOM_ODFacet_xh
  56. #include <Facet.xh>
  57. #endif
  58.  
  59. #ifndef SOM_ODFrame_xh
  60. #include <Frame.xh>
  61. #endif
  62.  
  63. #ifndef _TEMPOBJ_
  64. #include <TempObj.h>
  65. #endif
  66.  
  67. #ifndef _TEMPITER_
  68. #include <TempIter.h>
  69. #endif
  70.  
  71. #ifndef SOM_ODStorageUnit_xh
  72. #include <StorageU.xh>
  73. #endif
  74.  
  75. #ifndef SOM_ODSession_xh
  76. #include <ODSessn.xh>
  77. #endif
  78.  
  79. #ifndef SOM_ODFrameFacetIterator_xh
  80. #include "FrFaItr.xh"
  81. #endif
  82.  
  83. // -- OpenDoc Utilities --
  84.  
  85. #ifndef _ODDEBUG_
  86. #include <ODDebug.h>
  87. #endif
  88.  
  89. #ifndef _UTILERRS_
  90. #include "UtilErrs.h"
  91. #endif
  92.  
  93. #ifndef _STDTYPIO_
  94. #include "StdTypIO.h"
  95. #endif
  96.  
  97. #ifndef _ODUTILS_
  98. #include "ODUtils.h"
  99. #endif
  100.  
  101. #ifndef _STORUTIL_
  102. #include <StorUtil.h>
  103. #endif
  104.  
  105. #ifndef _FOCUSLIB_
  106. #include "FocusLib.h"
  107. #endif
  108.  
  109. #ifndef _ORDCOLL_
  110. #include "OrdColl.h"
  111. #endif
  112.  
  113. #ifndef _ODMEMORY_
  114. #include "ODMemory.h"
  115. #endif
  116.  
  117. // -- Toolbox Includes --
  118.  
  119. #ifndef mathRoutinesIncludes
  120. #include <math routines.h>
  121. #endif
  122.  
  123. #ifndef __MEMORY__
  124. #include <memory.h>
  125. #endif
  126.  
  127. #ifndef __DRAG__
  128. #include <Drag.h>
  129. #endif
  130.  
  131. // **************************** Need to improve Handling of Failure **********************
  132.  
  133. //=============================================================================
  134. // CSelection
  135. //=============================================================================
  136.  
  137.  
  138. //-----------------------------------------------------------------------------
  139. // CSelection::CSelection
  140. //-----------------------------------------------------------------------------
  141.  
  142. CSelection::CSelection(DrawEditor* editor, ODBoolean allowPublish, ODBoolean allowSubscribe) 
  143. {
  144.     fDrawEditor = editor;
  145.     
  146.     fEmbeddingShapeCount      = 0L;
  147.     fFrozenCount         = 0L;
  148.     
  149.     fUpdateShape = kODNULL;
  150.     fSelectionRectangle = gGlobals->fZeroRect;
  151.     
  152.     fAllowPublish = allowPublish;
  153.     fAllowSubscribe = allowSubscribe;
  154.  
  155.     fShapeList = new COrderedList;
  156.     fPublishLinks = new COrderedList;
  157.     fSubscribeLinks = new COrderedList;
  158.     
  159.     fPartialSubscribeCount = 0;
  160.     
  161.     fSelectionContent = new CSelectionContent(editor, fShapeList, fPublishLinks, fSubscribeLinks, this);
  162. }
  163.  
  164.  
  165. //-----------------------------------------------------------------------------
  166. // CSelection::~CSelection
  167. //-----------------------------------------------------------------------------
  168.  
  169. CSelection::~CSelection()
  170. {
  171.     Environment* ev = somGetGlobalEnvironment();
  172.  
  173.     ODSafeReleaseObject(fUpdateShape);
  174.     fUpdateShape = kODNULL;
  175.     
  176.     delete fShapeList;
  177.     delete fPublishLinks;
  178.     delete fSubscribeLinks;
  179.     
  180.     delete fSelectionContent;
  181. }
  182.  
  183.  
  184. //-----------------------------------------------------------------------------
  185. // CSelection::IsCompletelyUnfrozen
  186. //-----------------------------------------------------------------------------
  187.  
  188. ODBoolean CSelection::IsCompletelyUnfrozen() const
  189. {
  190.     return fShapeList->Count() != 0 && fFrozenCount != fShapeList->Count();
  191. }
  192.  
  193.  
  194. //-----------------------------------------------------------------------------
  195. // CSelection::SetFrozen
  196. //
  197. // Make all shapes currently in this collection frozen.
  198. //-----------------------------------------------------------------------------
  199.  
  200. void CSelection::SetFrozen(Environment* ev, ODBoolean state)
  201. {
  202.     COrdListIterator i(fShapeList);
  203.     for (CShape* shape = (CShape*) i.First(); i.IsNotComplete(); shape = (CShape*) i.Next())
  204.     {
  205.         if (shape->SetFrozen(state))
  206.         {
  207.             state ? fFrozenCount++ : fFrozenCount--;
  208.         }
  209.     }
  210. }
  211.  
  212.  
  213. //-----------------------------------------------------------------------------
  214. // CSelection::ContainsFrozen
  215. //-----------------------------------------------------------------------------
  216.  
  217. ODBoolean CSelection::ContainsFrozen() const
  218. {
  219.     return fFrozenCount != 0;
  220. }
  221.  
  222. //-----------------------------------------------------------------------------
  223. // CSelection::IsEmpty
  224. //-----------------------------------------------------------------------------
  225.  
  226. ODBoolean CSelection::IsEmpty() const
  227. {
  228.     return fShapeList->Count() == 0;
  229. }
  230.  
  231.  
  232. //-----------------------------------------------------------------------------
  233. // CSelection::Add
  234. //-----------------------------------------------------------------------------
  235.  
  236. void CSelection::Add(Environment* ev, CShape* shape)
  237. {
  238.     fShapeList->AddLast(shape);
  239.         
  240.     if (shape->GetShapeType() == kEmbeddingShape)
  241.         fEmbeddingShapeCount++;
  242.     if (shape->IsFrozen())
  243.         fFrozenCount++;
  244. }
  245.  
  246.  
  247. //-----------------------------------------------------------------------------
  248. // CSelection::Remove
  249. //-----------------------------------------------------------------------------
  250.  
  251. void CSelection::Remove(Environment* ev, CShape* shape)
  252. {
  253.     fShapeList->Remove(shape);
  254.  
  255.     if (shape->GetShapeType() == kEmbeddingShape)
  256.         fEmbeddingShapeCount--;
  257.     if (shape->IsFrozen())
  258.         fFrozenCount--;
  259. }
  260.  
  261. #pragma segment Main
  262. CEmbeddingShape* CSelection::IsOneEmbeddedShape(Environment* ev)
  263. {
  264.     // this access may be able to go away if we implement
  265.     // CDrawContent::HandleExternalize
  266.     
  267.     return fSelectionContent->IsOneEmbeddedShape(ev);
  268. }
  269.  
  270.  
  271. #pragma segment Main
  272. COrderedList* CSelection::GetShapeList()
  273. {
  274.     return fShapeList;
  275. }
  276.  
  277. #pragma segment Main
  278. CDrawContent* CSelection::GetSelectionContent()
  279. {
  280.     return fSelectionContent;
  281. }
  282.  
  283.  
  284. #pragma segment Main
  285. COrderedList* CSelection::GetPublishLinks()
  286. {
  287.     return fPublishLinks;    
  288. }
  289.  
  290.  
  291. #pragma segment Main
  292. COrderedList* CSelection::GetSubscribeLinks()
  293. {
  294.     return fSubscribeLinks;
  295. }
  296.  
  297. #pragma segment Main
  298. ODULong CSelection::Count()
  299. {
  300.     return fShapeList->Count();
  301. }
  302.  
  303.  
  304. #pragma segment Main
  305. DrawEditor* CSelection::GetDrawEditor()
  306. {
  307.     return fDrawEditor;
  308. }
  309.  
  310.  
  311. //-----------------------------------------------------------------------------
  312. //    CSelection::GetUpdateShape
  313. //-----------------------------------------------------------------------------
  314.  
  315. ODShape* CSelection::GetUpdateShape()
  316. {
  317.     return fUpdateShape;
  318. }
  319.  
  320. //-----------------------------------------------------------------------------
  321. //    CSelection::Dragging
  322. //-----------------------------------------------------------------------------
  323.  
  324. void CSelection::Dragging(Environment* ev, ODBoolean dragging )
  325. {
  326.     COrdListIterator ite(this->GetShapeList());
  327.     for (CShape *shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  328.     {
  329.         shape->Dragging(ev, dragging);
  330.     }
  331. }
  332.  
  333. //-----------------------------------------------------------------------------
  334. //    CSelection::GetSelectionRectangle
  335. //-----------------------------------------------------------------------------
  336.  
  337. void CSelection::GetSelectionRectangle(ODRect* rectangle)
  338. {
  339.     *rectangle = fSelectionRectangle;
  340. }
  341.  
  342.  
  343. //-----------------------------------------------------------------------------
  344. //    CSelection::ExternalizeSingleEmbeddedFrame
  345. //-----------------------------------------------------------------------------
  346.  
  347. void CSelection::ExternalizeSingleEmbeddedFrame(Environment* ev, 
  348.                                                 ODStorageUnit* storage, 
  349.                                                 CCloneInfo* info, 
  350.                                                 ODFrame* embeddedFrame)
  351. {
  352.     fSelectionContent->ExternalizeSingleEmbeddedFrame(ev, storage, 
  353.                                                         info, embeddedFrame);
  354. }
  355.  
  356. //-----------------------------------------------------------------------------
  357. //    CSelection::HandleInternalizeContent
  358. //-----------------------------------------------------------------------------
  359.  
  360. void CSelection::HandleInternalizeContent(Environment* ev, 
  361.                                     ODStorageUnit* storageUnit, 
  362.                                     CCloneInfo* info)
  363. {
  364.     fSelectionContent->HandleInternalizeContent(ev, storageUnit, info);
  365. }
  366.  
  367.  
  368. //-----------------------------------------------------------------------------
  369. //    CSelection::HandleTranslateContent
  370. //-----------------------------------------------------------------------------
  371.  
  372. void CSelection::HandleTranslateContent(Environment* ev, 
  373.                                             ODStorageUnit* storageUnit, 
  374.                                             CCloneInfo* info,
  375.                                             ODBoolean embedOrMerge)
  376. {
  377.     fSelectionContent->HandleTranslateContent(ev, storageUnit, info, embedOrMerge);
  378. }
  379.  
  380.  
  381. //-----------------------------------------------------------------------------
  382. //    CSelection::SetInLimbo
  383. //-----------------------------------------------------------------------------
  384.  
  385. void CSelection::SetInLimbo(Environment* ev, ODBoolean isInLimbo )
  386. {
  387.     COrdListIterator ite(fShapeList);
  388.     for (CShape *shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  389.     {
  390.         shape->SetInLimbo(ev, isInLimbo);
  391.     }
  392. }
  393.  
  394.  
  395. //-----------------------------------------------------------------------------
  396. //    CSelection::SelectedContentUpdated
  397. //-----------------------------------------------------------------------------
  398.  
  399. void CSelection::SelectedContentUpdated(Environment* ev, ODBoolean doClear)
  400. {
  401.  
  402.     COrderedList tempList;
  403.     
  404.     COrdListIterator iter(fShapeList);
  405.     for (CShape* shape = (CShape*)iter.First(); iter.IsNotComplete(); shape = (CShape*)iter.Next())
  406.     {            
  407.         COrderedList* pLinks = kODNULL;
  408.         CSubscribeLink* sLink = shape->GetSubscribeLink();
  409.         
  410.         if (sLink)
  411.             pLinks = sLink->GetPublishLinks();
  412.         else
  413.             pLinks = shape->GetPublishLinks();
  414.             
  415.         if (pLinks->Count() != 0)
  416.         {
  417.             COrdListIterator linkIter(pLinks);
  418.             for (CPublishLink* pLink = (CPublishLink*)linkIter.First(); linkIter.IsNotComplete(); pLink = (CPublishLink*)linkIter.Next())
  419.             {
  420.                 if (!pLink->WasRemoved())
  421.                     tempList.AddLast(pLink);
  422.             }
  423.         }
  424.     }
  425.  
  426.     // In a clear operation, we need to now actually clear the selection so that the updates to links and frame
  427.     // represent the changed content
  428.     if (doClear)
  429.     {
  430.         // Remove Subscribers.
  431.         while (fSubscribeLinks->Count() != 0)
  432.         {
  433.             CSubscribeLink *sLink = (CSubscribeLink*)fSubscribeLinks->RemoveFirst();
  434.             
  435.             // Remove the subscribe link and its shapes from the part and the selection.
  436.             // Setting the subscribe link as responsible for removing AND replacing shapes
  437.             // makes undo/redo of clear or cut safe and easy.
  438.             
  439.             sLink->RemoveFromPart(ev, kODTrue);  
  440.         }
  441.     
  442.         // Remove the remaining shapes.
  443.         CShape *shape;
  444.         while (fShapeList->Count() != 0)
  445.         {
  446.             shape = (CShape*)fShapeList->First();
  447.             Remove(ev, shape);                        // Remove from Selection list
  448.             shape->SelectShape(ev, kODFalse);        // (MH) Necessary to keep links working properly.
  449.             fDrawEditor->RemoveShape(ev, shape);    // Remove from shape list
  450.         }
  451.     }
  452.  
  453.     // Call ContentChanged on all shape links
  454.     ODUpdateID id = fDrawEditor->GetSession(ev)->UniqueUpdateID(ev);
  455.     
  456.     while (tempList.Count() != 0)
  457.     {
  458.         CPublishLink* pLink = (CPublishLink *)tempList.RemoveFirst();
  459.         
  460.         // tempList may contain duplicates, but update each link only once
  461.         if (pLink->GetUpdateID() != id)
  462.             pLink->ContentUpdated(ev, id);
  463.     }            
  464.     
  465.     // tell our display frame that we've changed too.  
  466.     fDrawEditor->ContentUpdated(ev, id);
  467.     
  468.     // Update shapes
  469.     CalcUpdateShape(ev);
  470. }
  471.  
  472.  
  473. //-----------------------------------------------------------------------------
  474. //    CSelection::IsSelectionPromised
  475. //-----------------------------------------------------------------------------
  476.  
  477. ODBoolean CSelection::IsPromisedToClipboard()
  478. {
  479.     COrdListIterator ite(fDrawEditor->GetShapeList());
  480.     for (CShape *shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  481.     {
  482.         if (shape->IsPromisedToClipboard())
  483.             return kODTrue;
  484.     }
  485.     return kODFalse;
  486. }
  487.  
  488.  
  489. //-----------------------------------------------------------------------------
  490. //    CSelection::ChangeSelectionColor
  491. //-----------------------------------------------------------------------------
  492.  
  493. void CSelection::ChangeSelectionColor(Environment* ev, const CRGBColor& color)
  494. {
  495.     COrdListIterator ite(fShapeList);
  496.     for (CShape *shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  497.     {
  498.         shape->SetColor(color);
  499.         fDrawEditor->InvalidateShape(ev, shape);
  500.     }
  501.     if (fShapeList->Count()>0)
  502.         SelectedContentUpdated(ev);
  503. }
  504.  
  505. //-----------------------------------------------------------------------------
  506. //    CSelection::RemoveFromSelection
  507. // This method assumes that we are focused for drawing.
  508. //-----------------------------------------------------------------------------
  509.  
  510. void CSelection::RemoveFromSelection(Environment* ev, 
  511.                                         CShape* theShape,
  512.                                         ODBoolean drawHandles)
  513. {
  514.     THROW_IF_NULL(theShape);
  515.     
  516.     if (theShape->IsSelected())
  517.     {
  518.         
  519.         this->Remove(ev, theShape);
  520.         theShape->SelectShape(ev, kODFalse);
  521.         
  522.         if (drawHandles)
  523.             this->DrawShapeHandles(ev, theShape, kODFalse);        // Turn Off
  524.     }        
  525.     else
  526.     {
  527.         // Make sure that the shape really isn't in the selection
  528.         #ifdef ODDebug
  529.         ASSERT(!fShapeList->Contains(theShape), kODErrAssertionFailed);
  530.         #endif
  531.     }    
  532.             
  533.     CalcUpdateShape(ev);
  534. }
  535.  
  536.  
  537. //-----------------------------------------------------------------------------
  538. //    CSelection::AddToSelection
  539. // This method assumes that we are focused for drawing.
  540. //-----------------------------------------------------------------------------
  541.  
  542. void CSelection::AddToSelection(Environment* ev,
  543.                                 CShape* theShape,
  544.                                 ODBoolean drawHandles)
  545. {
  546.     THROW_IF_NULL(theShape);
  547.     
  548.     if (!theShape->IsSelected())
  549.     {
  550.         theShape->SelectShape(ev, kODTrue);
  551.     
  552.         this->Add(ev, theShape);
  553.         this->DrawShapeHandles(ev, theShape, drawHandles);    
  554.     }
  555.     else
  556.     {
  557.         // Make sure that the shape really isn't in the selection
  558.         #ifdef ODDebug
  559.         ASSERT(fShapeList->Contains(theShape), kODErrAssertionFailed);
  560.         #endif
  561.     }    
  562.             
  563.     CalcUpdateShape(ev);
  564. }
  565.  
  566.  
  567. //-----------------------------------------------------------------------------
  568. //    CSelection::ClearSelection
  569. //-----------------------------------------------------------------------------
  570.  
  571. ODBoolean CSelection::ClearSelection(Environment* ev, ODFrame* frame)
  572. {
  573.  
  574.     // First remove publishers. This will prevent them from being updated when we call selection changed.
  575.     // It also prevents their shapes from actually being removed from their content when they are removed
  576.     // from the part so that if this is part 2 of a cut, a promise of a link made in part 1 can be fulfilled.
  577.     while (fPublishLinks->Count() != 0)
  578.     {
  579.         CPublishLink *pLink = (CPublishLink*)fPublishLinks->RemoveFirst();
  580.         pLink->RemoveFromPart(ev);
  581.     }
  582.     
  583.     // Now, call selection changed to update any partially contained publishers, and update our display frame
  584.     // while we still have the shapes (which point to the publishers.  By passing it the doClear = kODTrue
  585.     // it will actually remove the shapes. That's because it needs the shapes to know what links to update, 
  586.     // but can't actually update the links and the display frame until the shapes are removed.
  587.     this->SelectedContentUpdated(ev, kODTrue);
  588.     
  589.     // Clip Embedded Content ( Facets ) away here in case something in the selection
  590.     // was obscuring some embedded content.
  591.     fDrawEditor->ClipEmbeddedFacets(ev, frame);
  592.     
  593.     CalcUpdateShape(ev);
  594.     
  595.     return kODTrue;
  596. }
  597.  
  598. //-----------------------------------------------------------------------------
  599. //    CSelection::CloseSelection
  600. //-----------------------------------------------------------------------------
  601.  
  602. void CSelection::CloseSelection(Environment* ev)
  603. {
  604.     while (fShapeList->Count() != 0)
  605.     {
  606.         CShape *shape = (CShape*)fShapeList->First();
  607.         this->RemoveFromSelection(ev, shape, kODTrue);
  608.     }
  609.  
  610.     CalcUpdateShape(ev);
  611. }
  612.  
  613.  
  614. //-----------------------------------------------------------------------------
  615. //    CSelection::SelectAll
  616. //-----------------------------------------------------------------------------
  617.  
  618. void CSelection::SelectAll(Environment* ev, ODFrame* frame)
  619. {
  620.     DrawHandlesForAllFacets(ev, frame, kODFalse);
  621.  
  622.     COrdListIterator ite(fDrawEditor->GetShapeList());
  623.     for (CShape *shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  624.     {
  625.         if (!shape->IsSelected())
  626.         {
  627.             shape->SelectShape(ev, kODTrue);
  628.         
  629.             this->Add(ev, shape);
  630.             this->DrawShapeHandles(ev, shape, kODTrue);    
  631.         }
  632.     }
  633.     
  634.     DrawHandlesForAllFacets(ev, frame, kODTrue);
  635.  
  636.     CalcUpdateShape(ev);
  637.     
  638.     // Make sure the palette updates correctly
  639.     if (gGlobals->fToolPalette->GetSelectedPaletteItem()!=kSelectionTool)
  640.     {
  641.         ODSShort tItem = gGlobals->fToolPalette->GetSelectedPaletteItem();
  642.         
  643.         gGlobals->fToolPalette->SetSelectedPaletteItem(kSelectionTool);
  644.         gGlobals->fToolPalette->InvalidateTool(ev, tItem);
  645.         gGlobals->fToolPalette->InvalidateTool(ev, kSelectionTool);
  646.     }
  647. }
  648.  
  649.  
  650. //-----------------------------------------------------------------------------
  651. //    CSelection::DrawSelectionHandles
  652. //-----------------------------------------------------------------------------
  653.  
  654. void CSelection::DrawSelectionHandles(Environment* ev, ODFacet* facet, ODBoolean turnOn)
  655. {
  656.     CFocus draw(ev, facet);
  657.     
  658.     COrdListIterator i(fShapeList);
  659.     for (CShape* shape = (CShape*) i.First(); i.IsNotComplete(); shape = (CShape*) i.Next())
  660.     {
  661.         if ((shape->SetFrozen(turnOn))&&(turnOn))
  662.             shape->DrawHandles();    
  663.     }
  664. }
  665.  
  666.  
  667. //-----------------------------------------------------------------------------
  668. //    CSelection::InvalidateSelection
  669. // 
  670. // This method should be called when some object external to the selection
  671. // modifies the appearance of the selection and needs it to be redrawn.
  672. //-----------------------------------------------------------------------------
  673.  
  674. void CSelection::InvalidateSelection(Environment* ev, ODFrame* frame)
  675. {
  676.     COrdListIterator ite(fDrawEditor->GetShapeList());
  677.     for (CShape *shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  678.     {
  679.         fDrawEditor->InvalidateShape(ev, shape);
  680.     }
  681. }
  682.  
  683.  
  684. //-----------------------------------------------------------------------------
  685. //    CSelection::DrawHandlesForAllFacets
  686. //-----------------------------------------------------------------------------
  687. void CSelection::DrawHandlesForAllFacets(Environment* ev, ODFrame* frame, ODBoolean turnOn)
  688. {
  689.     if (fShapeList->Count() != 0)
  690.     {
  691.         ODFacet* facet;
  692.         ODFrameFacetIterator* fiter = frame->CreateFacetIterator(ev);
  693.         for ( facet = fiter->First(ev);
  694.               fiter->IsNotComplete(ev);
  695.               facet = fiter->Next(ev) )
  696.         {
  697.             DrawSelectionHandles(ev, facet, turnOn);
  698.         }
  699.     }
  700. }
  701.  
  702. //-----------------------------------------------------------------------------
  703. //    CSelection::Activate
  704. // Notify embedded contents of the selection that a frame is being 
  705. // activated/deactivated or a supend resume event has been received.
  706. //-----------------------------------------------------------------------------
  707. void CSelection::Activate(Environment* ev, ODBoolean activating, ODFrame* frame)
  708. {
  709.     COrdListIterator ite(fShapeList);
  710.     for (CShape* shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  711.     {
  712.         shape->Activate(ev, activating, frame);
  713.     }
  714. }
  715.  
  716. //-----------------------------------------------------------------------------
  717. //    CSelection::DrawShapeHandles
  718. //
  719. // Draw the shapes handles in all frames
  720. //-----------------------------------------------------------------------------
  721. void CSelection::DrawShapeHandles(Environment* ev, CShape* shape, ODBoolean turnOn)
  722. {
  723.     COrderedList* contentFrames = GetDrawEditor()->GetContentDisplayFrames(ev);
  724.     THROW_IF_NULL(contentFrames);
  725.         
  726.     if (contentFrames->Count()>0)
  727.     {
  728.         COrdListIterator iter(contentFrames);
  729.         for ( ODFrame* frame = (ODFrame*)iter.First();
  730.              iter.IsNotComplete();
  731.              frame = (ODFrame*)iter.Next() )
  732.         {
  733.             // invalidate handles
  734.             shape->InvalidateHandles(ev, frame);
  735.         }
  736.     }
  737.     
  738.     delete contentFrames;
  739. }
  740.  
  741. //-----------------------------------------------------------------------------
  742. //    CSelection::WhichHandle
  743. //-----------------------------------------------------------------------------
  744.  
  745. CShape* CSelection::WhichHandle(Environment* ev, ODFacet* facet, const Point& mouse, short* whichHandle) const
  746. {
  747.     *whichHandle = 0;
  748.     
  749.     if (fShapeList->Count() != 0)
  750.     {
  751.         COrdListIterator ite(fShapeList);
  752.         for (CShape *shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  753.         {
  754.             *whichHandle = shape->WhichHandle( mouse);
  755.             if (*whichHandle != 0)
  756.                 return shape;
  757.         }
  758.     }
  759.     
  760.     return NULL;
  761. }
  762.  
  763. //-----------------------------------------------------------------------------
  764. //    CSelection::TrackRectangle
  765. //-----------------------------------------------------------------------------
  766. ODBoolean CSelection::TrackRectangle(Environment* ev, ODEventData* event, Rect* selection)
  767. {
  768.     const Pattern kAntPattern = {0xEE, 0x77, 0xBB, 0xDD, 0xEE, 0x77, 0xBB, 0xDD};
  769.     
  770.     // If the mouse doesn't move, return
  771.     if (!::WaitMouseMoved(event->where))
  772.         return kODFalse;
  773.     
  774.     // Remember the pen state
  775.     ::PenState savePen;
  776.     ::GetPenState(&savePen);
  777.     
  778.     // Ant Pattern
  779.     ::PenMode(patXor);
  780.     ::PenPat(&kAntPattern);
  781.     
  782.     // Get the anchor point
  783.     Point anchorPoint = event->where;
  784.     ::GlobalToLocal(&anchorPoint);
  785.     
  786.     // Initialize the current and previous points
  787.     Point currentLoc = anchorPoint;
  788.         
  789.     // Track the rectangle
  790.     ODBoolean mouseMoved = kODTrue;
  791.     do  
  792.     {        
  793.         if (mouseMoved)
  794.         {
  795.             ::GetMouse(¤tLoc);
  796.             ::Pt2Rect(anchorPoint, currentLoc, selection);
  797.             ::FrameRect(selection);
  798.         }
  799.         
  800.         mouseMoved = ::WaitMouseMoved(currentLoc);
  801.         
  802.         if (mouseMoved)
  803.             ::FrameRect(selection);
  804.     } 
  805.     while (::WaitMouseUp());
  806.     
  807.     // If WaitMouseMoved returned false before the mouseup, then turn off
  808.     // the selection rectangle.
  809.     if (!mouseMoved)
  810.         FrameRect(selection);
  811.     
  812.     ::Pt2Rect(anchorPoint, currentLoc, selection);
  813.     
  814.     // Restore the pen state
  815.     ::SetPenState(&savePen);
  816.     
  817.     return kODTrue;
  818.  
  819. }
  820.  
  821. //-----------------------------------------------------------------------------
  822. //    CSelection::SelectWithShape
  823. //-----------------------------------------------------------------------------
  824. void CSelection::SelectWithShape(Environment* ev, 
  825.                                     ODFacet* facet, 
  826.                                     ODEventData* event,
  827.                                     CShape* shape)
  828. {    
  829.     // If the shift key is down, extend selection
  830.     if (event->modifiers & shiftKey)
  831.     {
  832.         if (shape->IsSelected())
  833.             this->RemoveFromSelection(ev, shape, TRUE);
  834.         else
  835.             this->AddToSelection(ev, shape, TRUE);
  836.     }
  837.     else if (!shape->IsSelected())
  838.     {
  839.         this->CloseSelection(ev);
  840.         this->AddToSelection(ev, shape, TRUE);
  841.     }            
  842.     
  843.     // If the mouse doesn't move, don't bother dragging
  844.     if (!WaitMouseMoved(event->where))
  845.         return;
  846.     
  847.     // if a shape is selected start dragging
  848.     if (shape->IsSelected())
  849.     {
  850.         CDragShapeCommand* dragCommand = 
  851.             new CDragShapeCommand(fDrawEditor, facet, this, 
  852.                                     event, kODTrue, kODTrue);
  853.         
  854.         if (dragCommand)
  855.         {
  856.             fDrawEditor->ExecuteCommand(ev, dragCommand);
  857.         }
  858.     }
  859. }
  860.             
  861. //-----------------------------------------------------------------------------
  862. //    CSelection::SelectWithRectangle
  863. //-----------------------------------------------------------------------------
  864. void CSelection::SelectWithRectangle(Environment* ev, ODFacet* facet, ODEventData*    event)
  865. {    
  866.     // Need to be focused for drawing for visual feedback
  867.     CFocus draw(ev, facet);
  868.     
  869.     ODBoolean isShift = event->modifiers & shiftKey;
  870.     
  871.     Rect selectRect;
  872.         
  873.     if (this->TrackRectangle(ev, event, &selectRect))
  874.     {
  875.         
  876.         COrdListIterator ite(fDrawEditor->GetShapeList());
  877.         for (CShape *shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  878.         {
  879.             if (shape->ShapeInRectangle(selectRect))
  880.             {
  881.                 if (shape->IsSelected())
  882.                 {
  883.                     if (isShift)
  884.                     {
  885.                         Remove(ev, shape);
  886.                         shape->SelectShape(ev, kODFalse);
  887.                         DrawShapeHandles(ev, shape, kODFalse);        // Turn Off
  888.                     }
  889.                 }
  890.                 else
  891.                 {
  892.                     Add(ev, shape);
  893.                     shape->SelectShape(ev, kODTrue);
  894.                     DrawShapeHandles(ev, shape, kODTrue);    // Turn on    
  895.                 }
  896.             }
  897.             else if (shape->IsSelected() && !isShift)
  898.             {
  899.                 shape->SelectShape(ev, kODFalse);
  900.                 Remove(ev, shape);
  901.                 DrawShapeHandles(ev, shape, kODFalse);        // Turn Off
  902.             }
  903.         }            
  904.         CalcUpdateShape(ev);
  905.     }
  906.     else
  907.     {
  908.         CloseSelection(ev);
  909.     }
  910.  
  911. }
  912.  
  913. //-----------------------------------------------------------------------------
  914. //    CSelection::CreateDragShape
  915. //-----------------------------------------------------------------------------
  916. ODShape* CSelection::CreateDragShape(Environment* ev, ODFacet* facet, ODFrame* frame)
  917. {
  918.     ODShape* dragShape = facet->CreateShape(ev);
  919.     
  920.     ODRect tRect(fSelectionRectangle);
  921.     
  922.     dragShape->SetRectangle(ev, &tRect);
  923.     
  924.     // Outline the shape in preparation for drag feedback
  925.     ODShape* tShape = dragShape->Copy(ev);
  926.     tShape->Outset(ev, ff(-1));
  927.     dragShape->Subtract(ev, tShape);
  928.     
  929.     // Release ref counted geometry
  930.     ODReleaseObject(ev, tShape);
  931.     
  932.     return dragShape;
  933. }
  934.  
  935. //-----------------------------------------------------------------------------
  936. //    CSelection::CalcUpdateShape
  937. //-----------------------------------------------------------------------------
  938. void CSelection::CalcUpdateShape(Environment* ev)
  939. {
  940.     fSelectionRectangle = gGlobals->fZeroRect;
  941.     
  942.     TRY
  943.         // Find a factory for temp shape creation
  944.         ODFrame* tFrame = this->GetDrawEditor()->GetANYFrame(ev);
  945.         THROW_IF_NULL(tFrame);
  946.         
  947.         if (fUpdateShape == NULL)
  948.             fUpdateShape = tFrame->CreateShape(ev);
  949.         
  950.         if (fShapeList->Count() == 0)
  951.             return;
  952.         
  953.         TempODShape aqTempShape = tFrame->CreateShape(ev);
  954.         Rect tempRect;
  955.     
  956.         ODBoolean first = kODTrue;
  957.         
  958.         COrdListIterator iter(fShapeList);
  959.         for ( CShape* shape = (CShape*)iter.First();
  960.              iter.IsNotComplete();
  961.              shape = (CShape*)iter.Next() )
  962.         {
  963.             shape->GetDragRect(&tempRect);
  964.             shape->GetUpdateShape(ev, aqTempShape);
  965.             if (first)
  966.             {
  967.                 fSelectionRectangle = tempRect;
  968.                 fUpdateShape->CopyFrom(ev, aqTempShape);
  969.             }
  970.             else
  971.             {
  972.                 UnionRect(&fSelectionRectangle, &tempRect, &fSelectionRectangle);
  973.                 fUpdateShape->Union(ev, aqTempShape);
  974.             }
  975.                             
  976.             first = kODFalse;
  977.         }
  978.         
  979.     CATCH_ALL
  980.         #ifdef ODDebug
  981.         DebugStr("\p Exception thrown creating facets!");
  982.         #endif
  983.     ENDTRY
  984. }
  985.  
  986. //-----------------------------------------------------------------------------
  987. //    CSelection::TrackResize
  988. //-----------------------------------------------------------------------------
  989. void CSelection::TrackResize(Environment* ev,
  990.                                 ODFacet* facet,
  991.                                 ODEventData* event,
  992.                                 ODSShort whichHandle, 
  993.                                 CShape* shape, 
  994.                                 Point* result)
  995. {
  996.  
  997.     const Pattern kAntPattern = {0xEE, 0x77, 0xBB, 0xDD, 0xEE, 0x77, 0xBB, 0xDD};
  998.     
  999.     // Need to be focused for drawing for visual feedback
  1000.     CFocus draw(ev, facet);
  1001.         
  1002.     // Remember the pen state
  1003.     ::PenState savePen;
  1004.     ::GetPenState(&savePen);
  1005.     
  1006.     // Ant Pattern
  1007.     ::PenMode(patXor);
  1008.     ::PenPat(&kAntPattern);
  1009.  
  1010.     // Track the rectangle
  1011.     do  
  1012.     {        
  1013.         ::GetMouse(result);
  1014.     
  1015.         // shape->GetResizeRect(whichHandle, currentLoc, result);
  1016.         shape->ResizeFeedback(facet, whichHandle, *result, kODTrue);
  1017.                         
  1018.         if (::WaitMouseMoved(*result))
  1019.         {
  1020.             shape->ResizeFeedback(facet, whichHandle, *result, kODFalse);
  1021.         }
  1022.         
  1023.     } 
  1024.     while (::WaitMouseUp());
  1025.     
  1026.     shape->ResizeFeedback(facet, whichHandle, *result, kODFalse);
  1027.     
  1028.     // Restore the pen state
  1029.     SetPenState(&savePen);
  1030. }
  1031.  
  1032. //-----------------------------------------------------------------------------
  1033. //    CSelection::Resize
  1034. //-----------------------------------------------------------------------------
  1035. void CSelection::Resize(Environment* ev, 
  1036.                                 CShape* anchor,
  1037.                                 ODFacet* containingFacet, 
  1038.                                 short whichHandle, 
  1039.                                 ODEventData* event)
  1040. {
  1041.     Point result;
  1042.     Rect baseRect, resizeRect;
  1043.     ODBoolean validRect;
  1044.     
  1045.     // If the mouse doesn't move, return
  1046.     if (!WaitMouseMoved(event->where))
  1047.         return;
  1048.         
  1049.     // Track the resize
  1050.     TrackResize(ev, containingFacet, event, whichHandle, anchor, &result);
  1051.     
  1052.     // Get & Validate the resize rectangle
  1053.     anchor->GetResizeRect(whichHandle, result, &baseRect, &resizeRect );
  1054.     validRect = !::EmptyRect(&resizeRect);
  1055.     
  1056.     if (validRect == kODTrue)
  1057.     {
  1058.         // Create & Execute resize command
  1059.         CResizeSelectionCommand* command = new 
  1060.             CResizeSelectionCommand(fDrawEditor, containingFacet, this, baseRect, resizeRect);
  1061.         THROW_IF_NULL(command);
  1062.             
  1063.         fDrawEditor->ExecuteCommand(ev, command);
  1064.         
  1065.     }
  1066. }
  1067.  
  1068.  
  1069.  
  1070. //-----------------------------------------------------------------------------
  1071. //    CSelection::ResizeSelection
  1072. //-----------------------------------------------------------------------------
  1073. void CSelection::ResizeSelection(Environment* ev,
  1074.                                     ODFrame* containingFrame,
  1075.                                     Rect baseRect, 
  1076.                                     Rect resizeRect)
  1077. {
  1078.     ODShape* tUnionShape = fUpdateShape->Copy(ev);
  1079.     
  1080.     COrdListIterator ite(fShapeList);
  1081.     for (CShape* shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  1082.     {
  1083.         shape->Resize(ev, baseRect, resizeRect);
  1084.     }
  1085.  
  1086.     CalcUpdateShape(ev);
  1087.  
  1088.     tUnionShape->Union(ev, fUpdateShape);
  1089.         
  1090.     // Reset clipping
  1091.     fDrawEditor->ClipEmbeddedFacets(ev, containingFrame);
  1092.     
  1093.     // Invalidate move to / from area
  1094.     containingFrame->Invalidate(ev, tUnionShape, kODNULL);
  1095.     
  1096.     // Release ref counted geometry
  1097.     ODReleaseObject(ev, tUnionShape);
  1098. }
  1099.  
  1100.  
  1101. //-----------------------------------------------------------------------------
  1102. //    CSelection::OffsetSelection
  1103. //-----------------------------------------------------------------------------
  1104. void CSelection::OffsetSelection(Environment* ev,
  1105.                                     ODFrame* containingFrame,
  1106.                                     ODCoordinate hOffset, 
  1107.                                     ODCoordinate vOffset)
  1108. {
  1109.     ODShape* tUnionShape = fUpdateShape->Copy(ev);
  1110.     
  1111.     COrdListIterator ite(fShapeList);
  1112.     for (CShape* shape = (CShape*)ite.First(); ite.IsNotComplete(); shape = (CShape*)ite.Next())
  1113.     {
  1114.         shape->OffsetShape(ev, hOffset, vOffset);
  1115.     }
  1116.  
  1117.     CalcUpdateShape(ev);
  1118.  
  1119.     // Create a union of the old and the new shapes
  1120.     tUnionShape->Union(ev, fUpdateShape);
  1121.     
  1122.     // If there is an active border shape then it was probably dragged as well
  1123.     fDrawEditor->InvalidateActiveBorder(ev, containingFrame);
  1124.         
  1125.     // Reset clipping
  1126.     fDrawEditor->ClipEmbeddedFacets(ev, containingFrame);
  1127.     
  1128.     // Invalidate move to / from area
  1129.     containingFrame->Invalidate(ev, tUnionShape, kODNULL);
  1130.     
  1131.     // Release ref counted geometry
  1132.     ODReleaseObject(ev, tUnionShape);
  1133. }
  1134.  
  1135. #pragma segment DrawEditor
  1136. CPublishLink *CSelection::FindPublisher()
  1137. {
  1138.     CPublishLink *link = NULL;
  1139.     
  1140.     if (fPublishLinks->Count() > 0)
  1141.     {
  1142.         
  1143.         COrdListIterator linkIte(fPublishLinks);
  1144.         for (link = (CPublishLink*)linkIte.First(); linkIte.IsNotComplete(); link = (CPublishLink*)linkIte.Next())
  1145.         {
  1146.             // set theory:  If the link is a subset of the selection, and has the same number of shapes
  1147.             // as the selection, then it must be the selection
  1148.             
  1149.             if (link->Count() == fShapeList->Count())
  1150.                 break;
  1151.             else
  1152.                 link = NULL;
  1153.         }
  1154.     }
  1155.     
  1156.     return link;
  1157. }
  1158.  
  1159. #pragma segment DrawEditor
  1160. void        CSelection::AddShapeToPart(Environment* ev, CShape* shape)//Override
  1161. {
  1162.     // Add it to editor's content
  1163.     fDrawEditor->AddShape(ev, shape);
  1164.     
  1165. }
  1166.  
  1167. #pragma segment Main
  1168. void CSelection::AddPublishLink(CPublishLink* link)
  1169. {
  1170.     fPublishLinks->AddLast(link);
  1171. }
  1172.  
  1173.  
  1174. #pragma segment Main
  1175. void CSelection::RemovePublishLink(CPublishLink* link)
  1176. {
  1177.     fPublishLinks->Remove(link);
  1178. }
  1179.  
  1180.  
  1181. #pragma segment Main
  1182. void CSelection::AddSubscribeLink(CSubscribeLink* link)
  1183. {
  1184.     fSubscribeLinks->AddLast(link);
  1185.     --fPartialSubscribeCount;
  1186. }
  1187.  
  1188.  
  1189. #pragma segment Main
  1190. void CSelection::RemoveSubscribeLink(CSubscribeLink* link)
  1191. {
  1192.     fSubscribeLinks->Remove(link);
  1193.     ++fPartialSubscribeCount;
  1194. }
  1195.  
  1196.  
  1197. #pragma segment Main
  1198. void CSelection::IncrementPartialSubscribeCount(ODUShort increment)
  1199. {
  1200.     fPartialSubscribeCount += increment;
  1201. }
  1202.  
  1203.  
  1204. #pragma segment Main
  1205. ODBoolean CSelection::CanMoveSelectedContent(CSubscribeLink*& link)
  1206. {
  1207.     // This test returns false if there are any partially selected 
  1208.     // subscribers.  If there is just one partially selected subscriber
  1209.     // then that subscriber is returned in the link parameter.
  1210.     
  1211.     if (fPartialSubscribeCount  == 1)
  1212.     {
  1213.         COrdListIterator iter(fShapeList);
  1214.         for (CShape* shape = (CShape*)iter.First(); iter.IsNotComplete(); shape = (CShape*)iter.Next())
  1215.         {
  1216.             link = shape->GetSubscribeLink();
  1217.             if (link)
  1218.                 break;
  1219.         }
  1220.     
  1221.     }
  1222.     
  1223.     return this->CanMoveSelectedContent();
  1224. }
  1225.  
  1226.  
  1227. #pragma segment Main
  1228. ODBoolean CSelection::CanEditSelectedContent()
  1229. {
  1230.     return (!fPartialSubscribeCount &&  !fSubscribeLinks->Count());
  1231. }
  1232.  
  1233. ODBoolean CSelection::CanPublish()
  1234. {
  1235.     ODBoolean result =     (fPartialSubscribeCount == 0) && 
  1236.                         !fDrawEditor->IsReadOnly() && 
  1237.                         (fDrawEditor->GetLinkStatus() != kODInLinkDestination);
  1238.                         
  1239.     if (result && fSubscribeLinks->Count() == 1)
  1240.     {
  1241.         CSubscribeLink* link = (CSubscribeLink*)fSubscribeLinks->First();
  1242.         result = fShapeList->Count() > link->Count();
  1243.     }
  1244.     
  1245.     return result;
  1246.         
  1247. }
  1248.  
  1249. #pragma segment Main
  1250. ODBoolean CSelection::CanMoveSelectedContent()
  1251. {
  1252.     return (fPartialSubscribeCount == 0);
  1253. }
  1254.  
  1255.  
  1256. #pragma segment Main
  1257. ODBoolean CSelection::CanEditSelectedContent(CSubscribeLink*& link)
  1258. {
  1259.     ODULong count = fPartialSubscribeCount + fSubscribeLinks->Count();
  1260.  
  1261.     if (count == 1)
  1262.     {
  1263.         link = (CSubscribeLink*)fSubscribeLinks->First();
  1264.         
  1265.         if (!link)
  1266.         {
  1267.             COrdListIterator iter(fShapeList);
  1268.             for (CShape* shape = (CShape*)iter.First(); iter.IsNotComplete(); shape = (CShape*)iter.Next())
  1269.             {
  1270.                 link = shape->GetSubscribeLink();
  1271.                 if (link)
  1272.                     break;
  1273.             }
  1274.         }        
  1275.     }
  1276.     
  1277.     return (count == 0);
  1278. }
  1279.  
  1280.  
  1281. #pragma segment Main
  1282. ODBoolean CSelection::IsOneLink()
  1283. {
  1284.     //  This is called to determine if there is an unambiguous link that can be accessed using 
  1285.     //  a link info dialog. 
  1286.     
  1287.     //    $$$$$ we're going to make it easy on ourselves by ignoring any partially selected publish links.
  1288.     //  this just means that to use link info, the user must select an entire publish link.
  1289.     //  the alternative, is to walk each shape and each shape's list of publishers to insure that there
  1290.     //     is only one publisher represented.  A more efficient approach would be to maintain an 
  1291.     //  fPartialPublishCount as we do now an fPartialSubscribeCount.
  1292.     
  1293.     ODULong count =  fPartialSubscribeCount + fSubscribeLinks->Count() + fPublishLinks->Count();
  1294.     
  1295.     return (count == 1);
  1296.     
  1297. }
  1298.  
  1299.  
  1300.  
  1301.